var GameControl = function () {

    var isGameOver = null;

    var gameScore = null;

    var timer = null;

    var speed = null;

    var compareSpeed = null;

    var arrayMap = null;

    var blockMap = null;

    var current = null;

    var currentBlock = null;

    var currentBlockArray = null;

    var currentBlockType = null;

    var gameTime = null;

    var isGamePause = false;

    var randomIndex = null;

    var nextBlockArray = null;

    // 初始化地图二维数组
    var initArrayMap = function () {
        var gameMap = [];
        for (var i = 0; i < 20; i++) {
            gameMap[i] = [];
            for (var j = 0; j < 10; j++) {
                gameMap[i][j] = GameConstant.blockType.typeZore;
            }
        }
        return gameMap;
    };

    // 初始化游戏地图
    var initBlockMap = function (arrayMap) {
        var game = document.getElementById("game");
        game.innerHTML = '';
        var gameBlocks = [];
        for (var i = 0; i < arrayMap.length; i++) {
            var gameBlock = [];
            for (var j = 0; j < arrayMap[i].length; j++) {
                var newBlock = document.createElement("div");
                newBlock.className = GameConstant.class.none;
                newBlock.style.top = (i * 20) + "px";
                newBlock.style.left = (j * 20) + "px";
                game.appendChild(newBlock);
                gameBlock.push(newBlock);
            }
            gameBlocks.push(gameBlock);
        }
        return gameBlocks;
    };

    // 刷新游戏地图
    var gameRefresh = function (arrayMap, blockMap) {
        gameOver();
        gameRemoveLine();
        changeGameSpeed();
        for (var i = 0; i < arrayMap.length; i++) {
            for (var j = 0; j < arrayMap[i].length; j++) {
                if (arrayMap[i][j] === GameConstant.blockType.typeZore) {
                    blockMap[i][j].className = GameConstant.class.none;
                } else if (arrayMap[i][j] === GameConstant.blockType.typeOne) {
                    blockMap[i][j].className = GameConstant.class.activeOne;
                }  else if (arrayMap[i][j] === GameConstant.blockType.typeTwo) {
                    blockMap[i][j].className = GameConstant.class.activeTwo;
                } else if (arrayMap[i][j] === GameConstant.blockType.typeThree) {
                    blockMap[i][j].className = GameConstant.class.activeThree;
                } else if (arrayMap[i][j] === GameConstant.blockType.typeFour) {
                    blockMap[i][j].className = GameConstant.class.activeFour;
                } else if (arrayMap[i][j] === GameConstant.blockType.typeFive) {
                    blockMap[i][j].className = GameConstant.class.activeFive;
                } else if (arrayMap[i][j] === GameConstant.blockType.typeSix) {
                    blockMap[i][j].className = GameConstant.class.activeSix;
                } else if (arrayMap[i][j] === GameConstant.blockType.typeSeven) {
                    blockMap[i][j].className = GameConstant.class.activeSeven;
                } else if (arrayMap[i][j] === GameConstant.blockType.typeEight) {
                    blockMap[i][j].className = GameConstant.class.fasten;
                }
            }
        }
    };

    /**
     * 绑定键盘事件
     */
    var bindKeyEvent = function () {
        document.onkeydown = function (event) {
            if (event.keyCode === GameConstant.keyCode.rotate) { // Up
                if(!isGamePause) {
                    gameKeyRotate();
                }
            } else if (event.keyCode === GameConstant.keyCode.right) { // Right
                if(!isGamePause) {
                    gameKeyRight();
                }
            } else if (event.keyCode === GameConstant.keyCode.down) { // Down
                if(!isGamePause) {
                    gameKeyDown();
                }
            } else if (event.keyCode === GameConstant.keyCode.left) { // Left
                if(!isGamePause) {
                    gameKeyLeft();
                }
            } else if (event.keyCode === GameConstant.keyCode.quick) { // Space
                if(!isGamePause) {
                    gameKeyQuick();
                }
            } else if(event.keyCode === GameConstant.keyCode.pause) {
                gamePause();
            } else if(event.keyCode === GameConstant.keyCode.score) {
                cheatAddScore();
            } else {
                // console.log(event.keyCode);
            }
        }
    };

    /**
     * 显示下一个方块
     * @returns {Array}
     */
    var showNextBlock = function () {
        var gameNext = document.getElementById("game-next");
        gameNext.innerHTML = '';
        var gameNextBlocks = [];
        for (var i = 0; i < nextBlockArray.length; i++) {
            var gameNextBlock = [];
            for (var j = 0; j < nextBlockArray[i].length; j++) {
                var newNextBlock = document.createElement("div");
                if(nextBlockArray[i][j] === GameConstant.blockType.typeZore) {
                    newNextBlock.className = GameConstant.class.none;
                } else if (nextBlockArray[i][j] === GameConstant.blockType.typeOne) {
                    newNextBlock.className = GameConstant.class.activeOne;
                }  else if (nextBlockArray[i][j] === GameConstant.blockType.typeTwo) {
                    newNextBlock.className = GameConstant.class.activeTwo;
                } else if (nextBlockArray[i][j] === GameConstant.blockType.typeThree) {
                    newNextBlock.className = GameConstant.class.activeThree;
                } else if (nextBlockArray[i][j] === GameConstant.blockType.typeFour) {
                    newNextBlock.className = GameConstant.class.activeFour;
                } else if (nextBlockArray[i][j] === GameConstant.blockType.typeFive) {
                    newNextBlock.className = GameConstant.class.activeFive;
                } else if (nextBlockArray[i][j] === GameConstant.blockType.typeSix) {
                    newNextBlock.className = GameConstant.class.activeSix;
                } else if (nextBlockArray[i][j] === GameConstant.blockType.typeSeven) {
                    newNextBlock.className = GameConstant.class.activeSeven;
                }
                newNextBlock.style.top = (i * 20) + "px";
                newNextBlock.style.left = (j * 20) + "px";
                gameNext.appendChild(newNextBlock);
                gameNextBlock.push(newNextBlock);
            }
            gameNextBlocks.push(gameNextBlock);
        }
        return gameNextBlocks;
    };

    /**
     * 更改游戏速度
     */
    var changeGameSpeed = function () {
        var minute = gameTime.getMinute();
        if(minute <= GameConstant.speed.minuteOne) {
            compareSpeed = GameConstant.speed.levelOne;
        } else if(minute <= GameConstant.speed.minuteTwo) {
            compareSpeed = GameConstant.speed.levelTwo;
        } else if(minute <= GameConstant.speed.minuteThree) {
            compareSpeed = GameConstant.speed.levelThree;
        } else if(minute <= GameConstant.speed.minuteFour) {
            compareSpeed = GameConstant.speed.levelFour;
        } else if(minute <= GameConstant.speed.minuteFive) {
            compareSpeed = GameConstant.speed.levelFive;
        } else if(minute <= GameConstant.speed.minuteSix) {
            compareSpeed = GameConstant.speed.levelSix;
        } else {
            compareSpeed = GameConstant.speed.levelSeven;
        }

        if(speed !== compareSpeed) {
            speed = compareSpeed;
            if(timer) {
                clearInterval(timer);
                timer = null;
                timer = setInterval(gameKeyDown, speed);
            }
        }
    };

    /**
     * 游戏暂停
     */
    var gamePause = function () {
        if(!isGamePause) {
            if(timer) {
                clearInterval(timer);
                timer = null;
            }
            gameTime.stopGameTime();
            isGamePause = true;
            document.getElementById("game-pause").style.display = "block";
        } else {
            timer = setInterval(gameKeyDown, speed);
            gameTime.startGameTime();
            isGamePause = false;
            document.getElementById("game-pause").style.display = "none";
        }
    };

    /**
     * 作弊加分
     */
    var cheatAddScore = function () {
        gameScore += 100;
        document.getElementById("score").innerHTML = gameScore + "";
    };

    /**
     * 初始化当前方块
     */
    var initCurrentBlock = function () {
        current = new GameBlock();
        currentBlock = current.initCurrentBlock(randomIndex);
        currentBlockArray = currentBlock.blockArray;
        currentBlockType = currentBlock.blockType;
        currentActive();

        randomIndex = getRandomIndex();

        var nextBlock = new GameBlock().initCurrentBlock(randomIndex);
        nextBlockArray = nextBlock.blockArray;

        showNextBlock();
    };

    var getRandomIndex = function () {
        randomIndex = Math.round(Math.random() * (GameConstant.activeBlockCount - 1));
        return randomIndex;
    };

    /**
     * 当前方块旋转或移动
     */
    var currentActive = function () {
        for (var i = 0; i < currentBlockArray.length; i++) {
            for (var j = 0; j < currentBlockArray[i].length; j++) {
                if (currentBlockArray[i][j] !== GameConstant.blockType.typeZore) {
                    arrayMap[current.coordinate.displayX + i][current.coordinate.displayY + j] = currentBlockArray[i][j];
                }
            }
        }
        gameRefresh(arrayMap, blockMap);
    };

    /**
     * 清除当前方块上次的状态
     */
    var clearLastTimeStatus = function () {
        for (var i = 0; i < currentBlockArray.length; i++) {
            for (var j = 0; j < currentBlockArray[i].length; j++) {
                if (currentBlockArray[i][j] === currentBlockType) {
                    arrayMap[current.coordinate.displayX + i][current.coordinate.displayY + j] = GameConstant.blockType.typeZore;
                }
            }
        }
    };

    // 方块向下
    var gameKeyDown = function () {
        if(!isGameOver) {
            if(current.isBlockActive) {
                blockMove(1, 0);
            } else {
                initCurrentBlock();
            }
        }

    };

    // 方块向左
    var gameKeyLeft = function () {
        blockMove(0, -1);
    };

    // 方块向右
    var gameKeyRight = function () {
        blockMove(0, 1);
    };

    // 快速向下
    var gameKeyQuick = function () {
        while(current.isBlockActive) {
            gameKeyDown();
        }
    };

    // 方块旋转
    var gameKeyRotate = function () {
        clearLastTimeStatus();
        blockRotate();
        currentActive();
    };

    // 游戏消行
    var gameRemoveLine = function () {
        var removeLineNum = 0;
        for (var i = 0; i < arrayMap.length; i++) {
            var canRemoveLine = true;
            for (var j = 0; j < arrayMap[i].length; j++) {
                if(arrayMap[i][j] !== GameConstant.blockType.typeEight) {
                    canRemoveLine = false;
                }
            }
            if(canRemoveLine) {
                removeLineNum += 1;
                for(var k = 0; k < arrayMap[i].length; k ++) {
                    arrayMap[i][k] = GameConstant.blockType.typeZore;
                }
                for(var m = i; m > 0; m --) {
                    for(var n = 0; n < arrayMap[m].length; n ++) {
                        arrayMap[m][n] = arrayMap[m - 1][n];
                    }
                }
            }
        }

        gameAddScore(removeLineNum);

    };

    // 游戏加分
    var gameAddScore = function (removeLineNum) {
        if(removeLineNum === 0) {
            return;
        }

        if(removeLineNum === 1) {
            gameScore += GameConstant.score.oneLine;
        } else if(removeLineNum === 2) {
            gameScore += GameConstant.score.twoLine;
        } else if(removeLineNum === 3) {
            gameScore += GameConstant.score.threeLine;
        } else if(removeLineNum === 4) {
            gameScore += GameConstant.score.fourLine;
        }
        document.getElementById("score").innerHTML = gameScore + "";

    };

    /**
     * 方块旋转
     * Ax = Oy + Ox - By
     * Ay = Oy - Ox + Bx
     */
    var blockRotate = function () {
        if(!current.isBlockActive) {
            return;
        }
        var newBlockArray = [
            [GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore],
            [GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore],
            [GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore],
            [GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore]
        ];
        if (currentBlockType !== GameConstant.blockType.typeSix && currentBlockType !== GameConstant.blockType.typeSeven) {
            for (var i = 0; i < currentBlockArray.length; i++) {
                for (var j = 0; j < currentBlockArray[i].length; j++) {
                    if (currentBlockArray[i][j] === currentBlockType) {
                        var newX = GameConstant.blockOrigin.y + GameConstant.blockOrigin.x - j;
                        var newY = GameConstant.blockOrigin.y - GameConstant.blockOrigin.x + i;
                        newBlockArray[newX][newY] = currentBlockType;
                    }
                }
            }
        } else if(currentBlockType === GameConstant.blockType.typeSix) {
            if(currentBlockArray[1][0] === currentBlockType) {
                newBlockArray = [
                    [GameConstant.blockType.typeZore, GameConstant.blockType.typeSix, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore],
                    [GameConstant.blockType.typeZore, GameConstant.blockType.typeSix, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore],
                    [GameConstant.blockType.typeZore, GameConstant.blockType.typeSix, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore],
                    [GameConstant.blockType.typeZore, GameConstant.blockType.typeSix, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore]
                ];
            } else {
                newBlockArray = [
                    [GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore],
                    [GameConstant.blockType.typeSix, GameConstant.blockType.typeSix, GameConstant.blockType.typeSix, GameConstant.blockType.typeSix],
                    [GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore],
                    [GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore, GameConstant.blockType.typeZore]
                ];
            }
        } else if(currentBlockType === GameConstant.blockType.typeSeven) {
            return;
        }
        var isCanRotate = true;
        for(var x = 0; x < newBlockArray.length; x ++) {
            for (var y = 0; y < newBlockArray[x].length; y++) {
                if(newBlockArray[x][y] === currentBlockType) {
                    if(isOverZone(current.coordinate.displayX + x, current.coordinate.displayY + y)
                        || isOverFastenBlock(current.coordinate.displayX + x, current.coordinate.displayY + y)) {
                        isCanRotate = false;
                    }
                }
            }
        }
        if(isCanRotate) {
            currentBlockArray = newBlockArray;
        }
    };

    /**
     * 方块移动
     * @param moveX 上下偏移量
     * @param moveY 左右偏移量
     */
    var blockMove = function (moveX, moveY) {
        if(!current.isBlockActive) {
            return;
        }
        var isCanMove = true;
        for(var i = 0; i < currentBlockArray.length; i ++) {
            for(var j = 0; j < currentBlockArray[i].length; j ++) {
                if(currentBlockArray[i][j] === currentBlockType) {
                    var newX = current.coordinate.displayX + i + moveX;
                    var newY = current.coordinate.displayY + j + moveY;
                    if(isOverZone(newX, newY) || isOverFastenBlock(newX, newY)) {
                        isCanMove = false;
                        break;
                    }
                }
            }
        }

        if(isCanMove) {
            clearLastTimeStatus();
            current.coordinate.displayX = current.coordinate.displayX + moveX;
            current.coordinate.displayY = current.coordinate.displayY + moveY;
        } else {
            var isFasten = false;
            for(var x = 0; x < currentBlockArray.length; x ++) {
                for (var y = 0; y < currentBlockArray[x].length; y++) {
                    if(currentBlockArray[x][y] === currentBlockType) {
                        if((current.coordinate.displayX + x + moveX) > GameConstant.mapSize.maxX) {
                            isFasten = true;
                            break;
                        } else if(moveX > 0 && isOverFastenBlock(current.coordinate.displayX + x + moveX, current.coordinate.displayY + y)) {
                            isFasten = true;
                            break;
                        }
                    }
                }
            }
            if(isFasten) {
                for(var l = 0; l < currentBlockArray.length; l ++) {
                    for (var m = 0; m < currentBlockArray[l].length; m++) {
                        if(currentBlockArray[l][m] === currentBlockType) {
                            currentBlockArray[l][m] = GameConstant.blockType.typeEight;
                        }
                    }
                }
                current.isBlockActive = false;
            }
        }
        currentActive();
    };

    /**
     * 游戏结束
     */
    var gameOver = function () {
        for(var i = 0; i < arrayMap[1].length; i ++) {
            if(arrayMap[1][i] === GameConstant.blockType.typeEight) {
                isGameOver = true;
                break;
            }
        }
        if(isGameOver) {
            if(timer) {
                clearInterval(timer);
                timer = null;
            }

            gameTime.stopGameTime();

            document.onkeydown = null;

            document.getElementById("over-score").innerHTML = gameScore + "";
            var evaluate = document.getElementById("evaluate");
            if(gameScore < GameConstant.evaluate.scoreOne) {
                evaluate.innerHTML = GameConstant.evaluate.levelOne;
            } else if(gameScore >= GameConstant.evaluate.scoreOne && gameScore < GameConstant.evaluate.scoreTwo) {
                evaluate.innerHTML = GameConstant.evaluate.levelTwo;
            } else if(gameScore >= GameConstant.evaluate.scoreTwo && gameScore < GameConstant.evaluate.scoreThree) {
                evaluate.innerHTML = GameConstant.evaluate.levelThree;
            } else if(gameScore >= GameConstant.evaluate.scoreThree && gameScore < GameConstant.evaluate.scoreFour) {
                evaluate.innerHTML = GameConstant.evaluate.levelFour;
            } else if(gameScore >= GameConstant.evaluate.scoreFour && gameScore < GameConstant.evaluate.scoreFive) {
                evaluate.innerHTML = GameConstant.evaluate.levelFive;
            } else if(gameScore >= GameConstant.evaluate.scoreFive && gameScore < GameConstant.evaluate.scoreSix) {
                evaluate.innerHTML = GameConstant.evaluate.levelSix;
            } else if(gameScore >= GameConstant.evaluate.scoreSix && gameScore < GameConstant.evaluate.scoreSeven) {
                evaluate.innerHTML = GameConstant.evaluate.levelSeven;
            } else {
                evaluate.innerHTML = GameConstant.evaluate.levelEight;
            }

            document.getElementById("game-over").style.display = "block";
        }

    };

    /**
     * 是否超出固定的方块
     */
    var isOverFastenBlock = function (calculationX, calculationY) {
        return arrayMap[calculationX][calculationY] === GameConstant.blockType.typeEight;
    };

    /**
     * 是否超出边界
     * @returns {boolean}
     */
    var isOverZone = function (calculationX, calculationY) {
        return (calculationX < GameConstant.mapSize.minX || calculationX > GameConstant.mapSize.maxX || calculationY < GameConstant.mapSize.minY || calculationY > GameConstant.mapSize.maxY)
    };

    var initGameData = function () {
        isGameOver = false;
        gameScore = 0;
        speed = GameConstant.speed.levelOne;
        compareSpeed = GameConstant.speed.levelOne;
        if(timer) {
            clearInterval(timer);
            timer = null;
        }
        document.onkeydown = null;

        arrayMap = null;
        blockMap = null;
        current = null;
        currentBlock = null;
        currentBlockArray = null;
        currentBlockType = null;
        gameTime = null;
        isGamePause = false;
        randomIndex = null;
        nextBlockArray = null;

        document.getElementById("score").innerHTML = gameScore + "";
    };

    this.initGame = function () {
        initGameData();

        gameTime = new GameTime();
        gameTime.startGameTime();

        arrayMap = initArrayMap();
        blockMap = initBlockMap(arrayMap);
        gameRefresh(arrayMap, blockMap);

        randomIndex = getRandomIndex();
        initCurrentBlock(randomIndex);

        bindKeyEvent();
        timer = setInterval(gameKeyDown, speed);
    };


};